跳到主要内容

C# 操作集合

C# 中的 Map集合

在 C# 中是没有 Map 这个类的,取而代之的是 “字典” 类型(Dictionary)

Dictionary<int, string> myDictionary = new Dictionary<int, string>(); 

myDictionary.Add("C#",0);
myDictionary.Add("C++",1);
myDictionary.Add("C",2);
myDictionary.Add("VB",2);

if(myDictionary.ContainsKey("C#"))
{
  Console.WriteLine("Key:{0},Value:{1}", "C#", myDictionary["C#"]);
}

遍历元素 By KeyValuePair 这是一种关系,和 Java中的 map.entry< , > 类似

foreach (KeyValuePair<string, int> kvp in myDictionary) 
{
  Console.WriteLine("Key = {0}, Value = {1}",kvp.Key, kvp.Value);
}

C# 多维数组

C# 支持多维数组。多维数组又称为矩形数组。它可以不用像 JavaScript 那么狼狈的通过循环取得

// 声明一个 string 变量的二维数组
string [,] names;

// 声明一个 int 变量的三维数组
int [ , , ] m;

// 访问二维数组元素
int val = a[2,3];

多维数组最简单的形式是二维数组。一个二维数组,在本质上,是一个一维数组的列表

初始化方式

int [,] a = new int [3,4] {
{0, 1, 2, 3} , /* 初始化索引号为 0 的行 */
{4, 5, 6, 7} , /* 初始化索引号为 1 的行 */
{8, 9, 10, 11} /* 初始化索引号为 2 的行 */
};

遍历方式

// 也无需像 js 那样创建一个临时变量来存储,直接通过 GetLength 就能获取不同的维度

// 一个遍历多维数组的例子,三重循环:
int[, ,] muarr = new int[2, 2, 3]
{
{{1,2,3},{4,5,6}},
{{7,8,9},{2,3,4}}
};


int rank = muarr.Rank;
Console.WriteLine("该多维数组的维数为:{0}",rank);
int rlength = muarr.GetLength(1);
Console.WriteLine("该多维数组的第二维有{0}个元素",rlength);
Console.WriteLine("开始遍历多维数组");
Console.WriteLine("----------------------------------");
int wei = 0;
for (int i = 0; i < muarr.GetLength(0);i++ )
{
for (int js1 = 0; js1< muarr.GetLength(1); js1++)
{
for(int js2 = 0;js2<muarr.GetLength(2);js2++)
{
Console.WriteLine("最低维度{0}的值为{1}",wei,muarr[i,js1,js2]);
}
++wei;
}
}

Linq 查询表达式

参考资料 Microsoft 官方文档 查询表达式基础 参考资料 C# Linq查询表达式总结

查询是一组指令,描述要从给定数据源(或源)检索的数据以及返回的数据应具有的形状和组织。 查询与它生成的结果不同。(就是 Java 的 Stream 那样的东西,不过它搞得更像 SQL 了)

从应用程序的角度来看,原始源数据的特定类型和结构并不重要。 应用程序始终将源数据视为 IEnumerable<T>IQueryable<T> 集合。 (总之就是集合对象)

例如在 LINQ to XML 中,源数据显示为 IEnumerable<XElement>

对于此源序列,查询可能会执行三种操作之一:

1、检索元素的子集以生成新序列,而不修改各个元素。 查询然后可能以各种方式对返回的序列进行排序或分组,如下面的示例所示(假定 scores 是 int[]):

IEnumerable<int> highScoresQuery =
from score in scores
where score > 80
orderby score descending
select score;

2、如前面的示例所示检索元素的序列,但是将它们转换为新类型的对象(类似 Java Stream 的 map 映射)。 例如,查询可以只从数据源中的某些客户记录检索姓氏。 或者可以检索完整记录,然后用于构造其他内存中对象类型甚至是 XML 数据,再生成最终的结果序列。 下面的示例演示从 int 到 string 的投影。 请注意 highScoresQuery 的新类型。

IEnumerable<string> highScoresQuery2 =
from score in scores
where score > 80
orderby score descending
select $"The score is {score}";

3、检索有关源数据的单独值,如:

  • 与特定条件匹配的元素数。
  • 具有最大或最小值的元素。
  • 与某个条件匹配的第一个元素,或指定元素集中特定值的总和。

例如,下面的查询从 scores 整数数组返回大于 80 的分数的数量:

int highScoreCount =
(from score in scores
where score > 80
select score)
.Count();

在前面的示例中,请注意在调用 Count 方法之前,在查询表达式两边使用了括号。 也可以通过使用新变量存储具体结果,来表示此行为。 这种方法更具可读性,因为它使存储查询的变量与存储结果的查询分开。

IEnumerable<int> highScoresQuery3 =
from score in scores
where score > 80
select score;

int scoreCount = highScoresQuery3.Count();

在上面的示例中,查询在 Count 调用中执行,因为 Count 必须循环访问结果才能确定 highScoresQuery 返回的元素数。

更多的细节参考官方文档

C# 中的 HashSet

HashSet 判断元素是否相等:

首先调用 hashCode 方法, 如果 hashCode 的值一样, 那么调用 equals 方法, 如果 equals 方法也一样, 那么才算重复元素, 不再添加  即: 1>重写 GethashCode() 2>重写 Equals()

这样 HashSet 在存储数据的时候即自动调用这两个方法进行判断是否是相同元素

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace test
{
public class DataBean
{
private int rows; //从 1开始
private int cols; //列下标从1开始
private int data;
// 1:选中 0:没选中 3:生成的数据点
private int isValid;

public DataBean()
{

}

public DataBean(int rows, int cols, int data, int isValid)
{
this.rows = rows;
this.cols = cols;
this.data = data;
this.isValid = isValid;
DataBean sb;
}

public int Rows { get => rows; set => rows = value; }
public int Cols { get => cols; set => cols = value; }
public int Data { get => data; set => data = value; }
public int IsValid { get => isValid; set => isValid = value; }

// 重写 hashCode 这里我只选择两个属性作为判断依据
public override int GetHashCode()
{
int result = 1;

int prime = 31;

result = prime * result + rows;
result = result * result + ((cols == 0) ? 0 : cols.GetHashCode());
return result;
}

public override bool Equals(object o)
{
if (o is DataBean s)
return (rows == s.rows)&& (cols ==s.cols) && (data == s.data) && (isValid == s.isValid);
else
return false;
}

}
}

TODO: 待更新...